package org.activequant.dao.hibernate.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.hibernate.SessionFactory;
import org.springframework.config.java.annotation.Bean;
import org.springframework.config.java.annotation.Configuration;
import org.springframework.config.java.annotation.ExternalValue;
import org.springframework.config.java.annotation.ResourceBundles;
import org.springframework.orm.hibernate3.LocalSessionFactoryBean;
/**
 * An abstract class. Annotated with:<br/>
 * <strong>@Configuration</strong><br/>
 * <strong>@ResourceBundles("classpath:/dao/hibernate/database")</strong>
 * @author Dimitar
 *
 */
@Configuration
@ResourceBundles("classpath:/dao/hibernate/database")
public abstract class LocalSessionFactoryConfig {

	@ExternalValue("database.driver")
	abstract String databaseDriver();

	@ExternalValue("database.url")
	abstract String databaseUrl();
	
	@ExternalValue("database.dialect")
	abstract String databaseDialect();

	@ExternalValue("database.showSql")
	abstract String databaseShowSql();

	@Bean(destroyMethodName="close")
	DataSource dataSource() {
		BasicDataSource source = new BasicDataSource();
		source.setDriverClassName(databaseDriver());
		source.setUrl(databaseUrl());
		return source;
	}
	
	@Bean
	public SessionFactory sessionFactory() {
		
		class LocalSessionFactoryAccessor extends LocalSessionFactoryBean {
			public SessionFactory accessSessionFactory() {
				return super.getSessionFactory();
			}
		}
		
		LocalSessionFactoryAccessor factory = new LocalSessionFactoryAccessor();

		Properties properties = new Properties();
		properties.setProperty("hibernate.hbm2ddl.auto", "update");
		properties.setProperty("hibernate.dialect", databaseDialect());
		properties.setProperty("hibernate.query.substitutions", "true 'T', false 'F'");
		properties.setProperty("hibernate.show_sql", databaseShowSql());
		properties.setProperty("hibernate.c3p0.minPoolSize", "5");
		properties.setProperty("hibernate.c3p0.maxPoolSize", "100");
		properties.setProperty("hibernate.c3p0.timeout", "300");
		properties.setProperty("hibernate.jdbc.batch_size", "20");
		properties.setProperty("hibernate.cache.use_second_level_cache", "true");
		properties.setProperty("hibernate.cache.use_query_cache", "true");
		properties.setProperty("hibernate.cache.provider_class", "org.hibernate.cache.EhCacheProvider");
		
		factory.setDataSource(dataSource());
		factory.setHibernateProperties(properties);
		factory.setMappingResources(new String [] {
				"dao/hibernate/domainmodel/candle.hbm.xml",
				"dao/hibernate/domainmodel/quote.hbm.xml",
				"dao/hibernate/domainmodel/tradeindication.hbm.xml",
//				"dao/hibernate/domainmodel/marketdepth.hbm.xml",
//				"dao/hibernate/domainmodel/marketdepthrow.hbm.xml",
				"dao/hibernate/domainmodel/marketdepthevent.hbm.xml",
				"dao/hibernate/domainmodel/instrumentspecification.hbm.xml",
				"dao/hibernate/domainmodel/account.hbm.xml",
				"dao/hibernate/domainmodel/balancebook.hbm.xml",
				"dao/hibernate/domainmodel/balanceentry.hbm.xml",
				"dao/hibernate/domainmodel/brokeraccount.hbm.xml",
				"dao/hibernate/domainmodel/order.hbm.xml",
				"dao/hibernate/domainmodel/orderhistory.hbm.xml",
				"dao/hibernate/domainmodel/orderevent.hbm.xml",
				"dao/hibernate/domainmodel/orderbook.hbm.xml",
				"dao/hibernate/domainmodel/portfolio.hbm.xml",
				"dao/hibernate/domainmodel/position.hbm.xml",
				"dao/hibernate/domainmodel/transaction.hbm.xml",
				"dao/hibernate/domainmodel/transactionbook.hbm.xml" ,
				"dao/hibernate/domainmodel/instrumentspecificationdetails.hbm.xml",
				"dao/hibernate/domainmodel/scancriteria.hbm.xml",
				"dao/hibernate/domainmodel/marketscan.hbm.xml",
				"dao/hibernate/domainmodel/tickernews.hbm.xml"
				}
		);
		
		try {
			factory.afterPropertiesSet();
			return factory.accessSessionFactory();
		} catch (Exception e) {
			e.printStackTrace();
			throw new AssertionError("failed to initialize session factory: can not continue");
		}
	}
}

